package main

import (
	"context"
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

type gh struct {
	ips map[string]time.Time
	sync.Mutex
}

func main() {
	var success int64
	var wait sync.WaitGroup
	wait.Add(1000 * 100)
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	aa := newObject(ctx)

	for i := 0; i < 1000; i++ {
		for j := 0; j < 100; j++ {
			go func(j int) {
				defer wait.Done()
				ip := fmt.Sprintf("192.168.1.%d", j)
				if !aa.isVisited(ip) {
					atomic.AddInt64(&success, 1)
				}
			}(j)
		}
	}
	wait.Wait()

	fmt.Println(success)
}

func newObject(ctx context.Context) (b *gh) {

	b = &gh{
		ips:   make(map[string]time.Time),
		Mutex: sync.Mutex{},
	}

	t := time.NewTimer(time.Minute*1)
	go func() {
		for {
			select {
			case <-ctx.Done():
				return
			case <-t.C:
				for k,v := range b.ips{
					if time.Now().Sub(v) >= time.Minute*1 {
						delete(b.ips,k)
					}
				}
				t.Reset(time.Minute*1)
			}
		}
	}()

	return
}

func (o *gh) isVisited(ip string) bool {
	o.Lock()
	defer o.Unlock()
	if _, ok := o.ips[ip]; ok {
		return true
	}
	o.ips[ip] = time.Now()
	return false
}
